﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using Excelhelper;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Threading;
using System.IO;
using OfficeOpenXml;
using MathWorks.MATLAB.NET.Arrays;  // MATLAB 数据 API
using MathWorks.MATLAB.NET.Utility;  // MATLAB 数据 API
using PIDControl;
using System.Runtime.InteropServices;
using DocumentFormat.OpenXml.Drawing;
using System.Text.RegularExpressions;
using DocumentFormat.OpenXml.Vml;


namespace 温室展示箱V1._2
{
    public partial class Form1 : Form
    {

        private ExcelWriter _excelWriter;
        //private System.Windows.Forms.Timer timer;
        private System.Windows.Forms.Timer timer1;
        private System.Windows.Forms.Timer timer2;
        private System.Windows.Forms.Timer timer3; //CO2温湿度传感器--读取CO2
        private System.Windows.Forms.Timer timer4; //EC值&水体温度
        private System.Windows.Forms.Timer timer5;
        private System.Windows.Forms.Timer timerE;  // 电度表
        private System.Windows.Forms.Timer timerPAR1;  // PAR1
        private System.Windows.Forms.Timer timerEC1;  // EC1
        private System.Windows.Forms.Timer timerpH1;  // pH1
        private System.Windows.Forms.Timer timer99;
        private System.Windows.Forms.Timer _closeMessageTimer;
        private System.Windows.Forms.Timer timerPID;
        private System.Windows.Forms.Timer LEDtimer;
        private CancellationTokenSource _cts; // 声明取消令牌源

        private bool isLedRelayOn = false;
        private bool isLEDTimerRunning = false;
        private bool isLEDRelayOn = false;
        private TimeSpan? userOpenTime;
        private TimeSpan? userCloseTime;
        private static int durationSeconds = 0;
        private static int durationMinutes = 0;
        private static bool isCO2On = false;

        private SerialPort port485;
        //设置第二个串口，用于控制继电器等
        private SerialPort port485_2;
        private SerialPort port485_3;
        private SerialPort port485_4;
        private SerialPort port485_5;


        //打开2路继电器一、二路开关的指令;连接、断开
        byte[] Modebus_Data_First_Connect = new byte[] { 0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A };
        byte[] Modebus_Data_First_DisConnect = new byte[] { 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xCA };
        byte[] Modebus_Data_Second_Connect = new byte[] { 0x01, 0x05, 0x00, 0x01, 0xFF, 0x00, 0xDD, 0xFA };
        byte[] Modebus_Data_Second_DisConnect = new byte[] { 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x9C, 0x0A };
        byte[] Modebus_Data_Third_Connect = new byte[] { 0x01, 0x05, 0x00, 0x02, 0xFF, 0x00, 0x2D, 0xFA };
        byte[] Modebus_Data_Third_DisConnect = new byte[] { 0x01, 0x05, 0x00, 0x02, 0x00, 0x00, 0x6C, 0x0A };


        //打开6路继电器一路开关的指令;连接、断开
        byte[] DAM_First_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8F, 0x84 };
        byte[] DAM_First_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x74 };
        byte[] DAM_Second_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x01, 0xFF, 0x00, 0xDE, 0x44 };
        byte[] DAM_Second_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x01, 0x00, 0x00, 0x9F, 0xB4 };
        byte[] DAM_Third_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x02, 0xFF, 0x00, 0x2E, 0x44 };
        byte[] DAM_Third_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x02, 0x00, 0x00, 0x6F, 0xB4 };
        byte[] DAM_Fourth_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x03, 0xFF, 0x00, 0x7F, 0x84 };
        byte[] DAM_Fourth_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x03, 0x00, 0x00, 0x3E, 0x74 };       
        byte[] DAM_Fifth_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x04, 0xFF, 0x00, 0xCE, 0x45 };
        byte[] DAM_Fifth_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x04, 0x00, 0x00, 0x8F, 0xB5 };
        byte[] DAM_Sixth_Connect = new byte[] { 0x1F, 0x05, 0x00, 0x05, 0xFF, 0x00, 0x9F, 0x85 };
        byte[] DAM_Sixth_DisConnect = new byte[] { 0x1F, 0x05, 0x00, 0x05, 0x00, 0x00, 0xDE, 0x75 };


        //读取温湿度传感器的相关指令,直接通过串口助手得到CRC校验位，迅速方便。
        //string Modebus_Data_temp = "02 04 00 00 00 02 71 F8";
        byte[] Modebus_Data_temp = new byte[] { 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xF8 };

        //打开光强传感器的串口
        //string Modebus_Data_Luminosity = "03 03 00 00 00 02 C5 E9";
        byte[] Modebus_Data_Luminosity = new byte[] { 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC5, 0xE9 };
        //CO2
        //byte[] Modebus_Data_CO2 = new byte[] { 0x04, 0x03, 0x01, 0x01, 0x00, 0x01, 0xD4, 0x63 };//旧版
        byte[] Modebus_Data_CO2 = new byte[] { 0x0B, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0xA0 };//xin版

        byte[] Modebus_Data_EC = new byte[] { 0x07, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x6D }; //EC/水体温度
        byte[] Modebus_Data_TopTemp = new byte[] { 0x08, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x93 }; //EC/水体温度
        byte[] Modebus_Data_Electric = new byte[] { 0x1E, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC6, 0x64 }; //电度表总耗能
        byte[] Modebus_Data_PAR1 = new byte[] { 0x0E, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0xF6 }; //PAR1
        byte[] Modebus_Data_EC1 = new byte[] { 0x0F, 0x04, 0x00, 0x00, 0x00, 0x03, 0xB1, 0x25 }; //EC1
        byte[] Modebus_Data_pH1 = new byte[] { 0x10, 0x04, 0x00, 0x00, 0x00, 0x02, 0x72, 0x8A }; //pH1
        



        bool isPort485Open = false;
        static string lastCommand = "";  // 记录最近发送的命令类型
        static StringBuilder buffer = new StringBuilder();  // 缓冲区存储数据
        private object saveTimer;

        // 定义 PID 参数
        private double Kp = 1.5;   // 比例系数
        private double Ki = 0.1;   // 积分系数
        private double Kd = 0.05;  // 微分系数
        private double previousError = 0;
        private double integral = 0;
        private int targetLuminosity = 0;  // 设定光强默认值设为 0
        private bool isPIDRunning = false; // PID 是否在运行

        public Form1()
        {
            InitializeComponent();
            FillTimeOptions();

            //系统时间定时器开始
            // 设置Timer以每秒更新时间
            System.Windows.Forms.Timer timer100 = new System.Windows.Forms.Timer();
            timer100.Interval = 1000*60; // 1min
            timer100.Tick += Timer_Tick100;
            timer100.Enabled = true;
            UpdateTime(); // 初始显示时间

            System.Windows.Forms.Timer saveTimer = new System.Windows.Forms.Timer();
            //saveTimer.Interval =  10 * 60 * 1000;  // 10 分钟
            saveTimer.Interval = 1000*60*1;  // 
            saveTimer.Tick += (s, e) => SaveDataToExcel();
            saveTimer.Start();


            // 初始化定时器
            LEDtimer = new System.Windows.Forms.Timer();
            LEDtimer.Interval = 1000*60; // 每秒触发
            LEDtimer.Tick += LEDTimer_Tick;
            //port485_2 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);

        }

        //初始化定时选项，主要用于控制LED灯的每日开关时间
        //private void InitializeComboBoxes()
        //{
        //    // 在窗体上动态添加两个ComboBox
        //    openTimeComboBox = new System.Windows.Forms.ComboBox
        //    {
        //        Location = new System.Drawing.Point(36, 380),
        //        Width = 100,
        //        DropDownStyle = ComboBoxStyle.DropDown
        //    };
        //    closeTimeComboBox = new System.Windows.Forms.ComboBox
        //    {
        //        Location = new System.Drawing.Point(56, 380),
        //        Width = 100,
        //        DropDownStyle = ComboBoxStyle.DropDown
        //    };

        //    // 添加标签
        //    var openLabel = new Label
        //    {
        //        Text = "开启时间:",
        //        Location = new System.Drawing.Point(66, 460),
        //        AutoSize = true
        //    };
        //    var closeLabel = new Label
        //    {
        //        Text = "关闭时间:",
        //        Location = new System.Drawing.Point(66, 400),
        //        AutoSize = true
        //    };

        //    // 添加控件到窗体
        //    this.Controls.Add(openTimeComboBox);
        //    this.Controls.Add(closeTimeComboBox);
        //    this.Controls.Add(openLabel);
        //    this.Controls.Add(closeLabel);

        //    // 填充时间选项（每15分钟）
        //    //FillTimeOptions();
        //}

 
        private void FillTimeOptions()
        {
            openTimeComboBox.Items.Clear();
            closeTimeComboBox.Items.Clear();

            for (int hour = 0; hour < 24; hour++)
            {
                for (int minute = 0; minute < 60; minute += 30)
                {
                    string timeString = $"{hour:D2}:{minute:D2}";
                    openTimeComboBox.Items.Add(timeString);
                    closeTimeComboBox.Items.Add(timeString);
                }
            }

            // 设置默认值
            openTimeComboBox.SelectedItem = "06:30";
            closeTimeComboBox.SelectedItem = "20:30";

            if (openTimeComboBox.Items.Count == 0)
            {
                MessageBox.Show("时间选项填充失败");
            }
        }

        private void Timer_Tick100(object sender, EventArgs e)
        {
            UpdateTime();
        }
        private void UpdateTime()
        {
            // 更新ToolStripStatusLabel显示当前时间
            toolStripStatusLabel1.Text = DateTime.Now.ToString("时间:" + "yyyy-MM-dd HH:mm");
        }

        //连接串口
        private void button1_Click(object sender, EventArgs e)
        {
            //#############判断是否连接成功，是否有电等情况#############
            try
            {
                if (!isPort485Open)
                {
                    port485 = new SerialPort($"{textBox1.Text}", 9600, Parity.None, 8, StopBits.One);

                    port485.Open(); // 打开串口
                    port485.DataReceived += Port485_DataReceived;  // 注册接收数据事件
                    isPort485Open = true;
                    button1.BackColor = System.Drawing.Color.Green;//改颜色
                    button1.Text = "已连接";
                    // 初始化定时器
                    //timer = new System.Windows.Forms.Timer();
                    //timer.Interval = 1000;  // 1 秒触发一次
                    //timer.Tick += Timer_Tick;  // 绑定定时器事件
                    //timer.Start();


                    //Thread.Sleep(1000);
                    timer1 = new System.Windows.Forms.Timer();
                    timer1.Interval = 1100;  // 1 秒触发一次
                    timer1.Tick += Timer1_Tick;  // 绑定定时器事件
                    timer1.Start();


                    //Thread.Sleep(1500);
                    timer3 = new System.Windows.Forms.Timer();
                    timer3.Interval = 1500;  // 1 秒触发一次
                    timer3.Tick += Timer3_Tick;  // 绑定定时器事件
                    timer3.Start();
                    
                    //EC&水体温度
                    //timer4 = new System.Windows.Forms.Timer();
                    //timer4.Interval = 1700;  // 1 秒触发一次
                    //timer4.Tick += Timer4_Tick;  // 绑定定时器事件
                    //timer4.Start();

                    //顶层水体温度
                    timer5 = new System.Windows.Forms.Timer();
                    timer5.Interval = 1800;  // 1 秒触发一次
                    timer5.Tick += Timer5_Tick;  // 绑定定时器事件
                    timer5.Start();

                    //电度表
                    timerE = new System.Windows.Forms.Timer();
                    //timer6.Interval = 1000*60;  // 1 秒触发一次
                    timerE.Interval = 2000;  // 2 秒触发一次
                    timerE.Tick += TimerE_Tick;  // 绑定定时器事件
                    timerE.Start();


                    //PAR-1
                    timerPAR1 = new System.Windows.Forms.Timer();
                    //timer6.Interval = 1000*60;  // 1 秒触发一次
                    timerPAR1.Interval = 2100;  // 2 秒触发一次
                    timerPAR1.Tick += TimerPAR1_Tick;  // 绑定定时器事件
                    timerPAR1.Start();
                    
                    //EC-1
                    timerEC1 = new System.Windows.Forms.Timer();
                    //timer6.Interval = 1000*60;  // 1 秒触发一次
                    timerEC1.Interval = 2200;  // 2 秒触发一次
                    timerEC1.Tick += TimerEC1_Tick;  // 绑定定时器事件
                    timerEC1.Start();
                    
                    //pH-1
                    timerpH1 = new System.Windows.Forms.Timer();
                    //timer6.Interval = 1000*60;  // 1 秒触发一次
                    timerpH1.Interval = 2300;  // 2 秒触发一次
                    timerpH1.Tick += TimerpH1_Tick;  // 绑定定时器事件
                    timerpH1.Start();

                }
                else //处于连接状态
                {
                    port485.Close();
                    isPort485Open = false;
                    button1.BackColor = System.Drawing.Color.Red;//改颜色
                    button1.Text = "未连接";
                    if (timer1 != null && timer3 != null &&  timer5 != null && timerE != null) //timer4 != null &&
                    {
                        //timer.Stop();
                        timer1.Stop();
                        timer3.Stop();
                        //timer4.Stop();
                        timer5.Stop();
                        timerE.Stop();
                        timerPAR1.Stop();
                        timerEC1.Stop();
                        timerpH1.Stop();
                        //timer.Dispose();
                        timer1.Dispose();
                        timer3.Dispose();
                        //timer4.Dispose();
                        timer5.Dispose();
                        timerE.Dispose();
                        timerPAR1.Dispose();
                        timerEC1.Dispose();
                        timerpH1.Dispose();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("无法连接串口: " + ex.Message);
            }
        }

        ////温湿度触发器设置
        //private void Timer_Tick(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        // 记录日志，检查定时器是否触发
        //        //Console.WriteLine("Timer_Tick triggered");

        //        lastCommand = "temp";
        //        port485.Write(Modebus_Data_temp, 0, Modebus_Data_temp.Length);
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show($"Error in Timer_Tick: {ex.Message}");

        //    }
        //}

        //读取光强
        private void Timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                // 记录日志，检查定时器是否触发
                //Console.WriteLine("Timer1_Tick triggered");

                lastCommand = "luminosity";
                port485.Write(Modebus_Data_Luminosity, 0, Modebus_Data_Luminosity.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in Timer1_Tick: {ex.Message}");
            }
        }


        //读取CO2
        private void Timer3_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "CO2";
                port485.Write(Modebus_Data_CO2, 0, Modebus_Data_CO2.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in Timer3_Tick: {ex.Message}");
            }
        }

        //读取EC&水体温度
        private void Timer4_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "EC";
                port485.Write(Modebus_Data_EC, 0, Modebus_Data_EC.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in Timer4_Tick: {ex.Message}");
            }
        } 
        
        //顶层水体温度
        private void Timer5_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "TopTemp";
                port485.Write(Modebus_Data_TopTemp, 0, Modebus_Data_TopTemp.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in Timer5_Tick: {ex.Message}");
            }
        }

        //总用电量
        private void TimerE_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "Electric";
                port485.Write(Modebus_Data_Electric, 0, Modebus_Data_Electric.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in TimerE_Tick: {ex.Message}");
            }
        }
        
        //PAR-1 
        private void TimerPAR1_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "PAR1";
                port485.Write(Modebus_Data_PAR1, 0, Modebus_Data_PAR1.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in TimerPAR_Tick: {ex.Message}");
            }
        }
        
        //EC-1 
        private void TimerEC1_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "EC1";
                port485.Write(Modebus_Data_EC1, 0, Modebus_Data_EC1.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in TimerPAR_Tick: {ex.Message}");
            }
        }
        
        //pH-1 
        private void TimerpH1_Tick(object sender, EventArgs e)
        {
            try
            {
                lastCommand = "pH1";
                port485.Write(Modebus_Data_pH1, 0, Modebus_Data_pH1.Length);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in TimerPAR_Tick: {ex.Message}");
            }
        }

        //触发事件--保存数据
        private void Timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                // 记录日志，每隔十分钟记录一次数据到excel

                SaveDataToExcel();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in Timer1_Tick: {ex.Message}");
            }
        }


        // 定时器事件，关闭弹窗
        private void CloseMessageBox(object sender, EventArgs e)
        {
            _closeMessageTimer.Stop();  // 停止定时器

            // 如果有未关闭的弹窗，可以通过其他方法关闭弹窗
            // 在WinForms中，MessageBox 没有直接的关闭方法，因此可以显示一个自定义的弹窗控件来代替。
        }

        //接收传感器的数据
        private void Port485_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                //MessageBox.Show("1 ");
                // 接收返回的数据
                int bytesToRead = port485.BytesToRead;
                byte[] receivedData = new byte[bytesToRead];
                port485.Read(receivedData, 0, bytesToRead);

                // 调试：打印接收到的数据
                string receivedHex = BitConverter.ToString(receivedData);
                //MessageBox.Show("接收到数据: " + receivedHex);

                // 解析数据
                this.BeginInvoke((MethodInvoker)(() =>
                {
                    ProcessReceivedData(receivedData);
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error in receiving data: {ex.Message}");
            }
        }


        // 解析数据
        private void ProcessReceivedData(byte[] receivedData)
        {
            if (receivedData.Length < 7) return;  // 确保数据完整

            //if (lastCommand == "temp")
            //{
            //    ParseTemperatureHumidity(receivedData);
            //}
            else if (lastCommand == "luminosity")
            {
                ParseLuminosity(receivedData);
            }
            else if (lastCommand == "CO2")
            {
                ParseCO2(receivedData);
            }           
            //else if (lastCommand == "EC")
            //{
            //    ParseEC(receivedData);
            //}
            else if (lastCommand=="TopTemp")
            {
                ParseTopTemp(receivedData);
            }
            else if (lastCommand=="Electric")
            {
                ParseElectric(receivedData);
            }
            else if (lastCommand=="PAR1")
            {
                ParsePAR1(receivedData);
            }
            else if (lastCommand=="EC1")
            {
                ParseEC1(receivedData);
            }
            else if (lastCommand=="pH1")
            {
                ParsepH1(receivedData);
            }
        }

        ////解析温湿度数据
        //private void ParseTemperatureHumidity(byte[] receivedData)
        //{
        //    if (receivedData.Length < 7) return;  // 避免索引越界

        //    bool isBigEndian = true;  // 你需要根据设备手册确认是否为大端模式

        //    byte[] group1 = new byte[] { receivedData[3], receivedData[4] };
        //    byte[] group2 = new byte[] { receivedData[5], receivedData[6] };

        //    if (isBigEndian)
        //    {
        //        Array.Reverse(group1);
        //        Array.Reverse(group2);
        //    }

        //    int value1 = BitConverter.ToUInt16(group1, 0);
        //    int value2 = BitConverter.ToUInt16(group2, 0);

        //    float temperature = value1 / 10.0f;
        //    float humidity = value2 / 10.0f;

        //    this.BeginInvoke((MethodInvoker)(() =>
        //    {
        //        textBox2.Text = $"温度: {temperature} ℃\r\n湿度: {humidity} %";
        //    }));
        //}


        // 解析光强数据
        private void ParseLuminosity(byte[] receivedData)
        {
            try
            {
                if (receivedData.Length < 5) return;  // 避免数组越界

                byte[] luminosityData = new byte[] { receivedData[5], receivedData[6] };

                bool isBigEndian = true; // 根据设备手册确认是否为大端模式
                if (isBigEndian)
                {
                    Array.Reverse(luminosityData);
                }

                int luminosity = BitConverter.ToUInt16(luminosityData, 0);

                this.BeginInvoke((MethodInvoker)(() =>
                {
                    textBox3.Text = $"光强: {luminosity} Lux";
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析光强数据错误: " + ex.Message);
            }
        }

        // 解析CO2数据
        private void ParseCO2(byte[] receivedData)
        {
            try
            {
                if (receivedData.Length < 3) return;  // 避免数组越界

                byte[] co2Data = new byte[] { receivedData[3], receivedData[4] };

                bool isBigEndian = true; // 根据设备手册确认是否为大端模式
                if (isBigEndian)
                {
                    Array.Reverse(co2Data);
                }

                int co2 = BitConverter.ToUInt16(co2Data, 0);

                this.BeginInvoke((MethodInvoker)(() =>
                {
                    textBox6.Text = $"CO2: {co2} ppm";
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析CO2数据错误: " + ex.Message);
            }
        }

        //解析EC&水体温度数据
        private void ParseEC(byte[] receivedData)
        {
            if (receivedData.Length < 7) return;  // 避免索引越界

            bool isBigEndian = true;  // 你需要根据设备手册确认是否为大端模式

            byte[] group1 = new byte[] { receivedData[3], receivedData[4] };
            byte[] group2 = new byte[] { receivedData[5], receivedData[6] };

            if (isBigEndian)
            {
                Array.Reverse(group1);
                Array.Reverse(group2);
            }

            int value1 = BitConverter.ToUInt16(group1, 0);
            int value2 = BitConverter.ToUInt16(group2, 0);
            Console.WriteLine("====== 调试输出 ======");
            Console.WriteLine($"group1 原始字节: {BitConverter.ToString(group1)} → 十进制: {value1}");
            Console.WriteLine($"group2 原始字节: {BitConverter.ToString(group2)} → 十进制: {value2}");


            float TempInTank = value1 / 10.0f;
            float EC = value2;

            this.BeginInvoke((MethodInvoker)(() =>
            {
                textBox7.Text = $"水温:{TempInTank} ℃\r\n EC:{EC} ";
            }));
        }


        // 解析顶层水温数据
        private void ParseTopTemp(byte[] receivedData)
        {
            try
            {
                if (receivedData.Length < 3) return;  // 避免数组越界

                byte[] TopTemp = new byte[] { receivedData[3], receivedData[4] };

                bool isBigEndian = true; // 根据设备手册确认是否为大端模式
                if (isBigEndian)
                {
                    Array.Reverse(TopTemp);
                }

                int TopTemp1 = BitConverter.ToUInt16(TopTemp, 0);

                this.BeginInvoke((MethodInvoker)(() =>
                {
                    textBox9.Text = $"顶层水温: {TopTemp1/10} ℃";
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析顶层水温数据错误: " + ex.Message);
            }
        }

        // 解析电度表总用电量数据
        private void ParseElectric(byte[] receivedData)
        {
            try
            {
                if (receivedData.Length < 3) return;  // 避免数组越界

                byte[] Electric = new byte[] { receivedData[3], receivedData[4], receivedData[5], receivedData[6]};

                bool isBigEndian = true; // 根据设备手册确认是否为大端模式
                if (isBigEndian)
                {
                    Array.Reverse(Electric);
                }

                double TotalElectric = BitConverter.ToUInt16(Electric, 0);

                this.BeginInvoke((MethodInvoker)(() =>
                {
                    textBox10.Text = $" {TotalElectric / 100} KWh";
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show("解析电表数据错误: " + ex.Message);
            }
        }

        // 解析PAR传感器数据（根据最新协议调整）
        private void ParsePAR1(byte[] receivedData)
        {
            try
            {
                // 1. 数据长度校验（您的新数据长度为14字节）
                if (receivedData.Length < 12)
                {
                    //MessageBox.Show($"数据长度不足14字节，当前长度：{receivedData.Length}");
                    return;
                }

                // 假设设备使用大端序（高位在前）
                bool isBigEndian = true;

                // 1. 设备地址（第3-4字节：00 0E）
                //byte[] addrBytes = { receivedData[3], receivedData[4] };
                //if (isBigEndian) Array.Reverse(addrBytes); // 大端模式需要反转字节序
                //ushort deviceAddress = BitConverter.ToUInt16(addrBytes, 0);

                // 2. PAR值（第5-6字节：00 86）
                byte[] parBytes = { receivedData[5], receivedData[6] };
                if (isBigEndian) Array.Reverse(parBytes);
                double parValue = BitConverter.ToUInt16(parBytes, 0) *0.1;

                // 3. 温度（第7-8字节：01 53 → 0x0153 → 339×0.1=33.9℃）
                byte[] tempBytes = { receivedData[7], receivedData[8] };
                if (isBigEndian) Array.Reverse(tempBytes);
                double temperature = BitConverter.ToUInt16(tempBytes, 0) / 10.0;

                // 4. 湿度（第9-10字节：02 57 → 0x0257 → 599÷10=59.9%RH）
                byte[] humiBytes = { receivedData[9], receivedData[10] };
                if (isBigEndian) Array.Reverse(humiBytes);
                double humidity = BitConverter.ToUInt16(humiBytes, 0) / 10.0;

    

                // 6. 显示结果（带单位转换验证提示）
                this.BeginInvoke((MethodInvoker)(() =>
                {
                    //textBox_Device.Text = $"设备地址: 0x{deviceAddress:X4} (原始字节: {BitConverter.ToString(addrBytes)})";
                    textBox16.Text = $"{parValue:F1}";
                    textBox2.Text = $"{temperature:F1}";
                    textBox17.Text = $"{humidity:F1}";
                }));

                // 7. 打印调试信息（控制台输出）
                //Console.WriteLine($"原始数据: {BitConverter.ToString(receivedData)}");
                //Console.WriteLine($"解析结果: PAR={parValue}, Temp={temperature:F1}℃, Humi={humidity:F1}%");
            }
            catch (Exception ex)
            {
                //MessageBox.Show($"解析错误！\n异常: {ex.Message}\n原始数据: {BitConverter.ToString(receivedData)}");
                ShowAutoCloseMessage($"解析错误: {ex.Message}");
            }
        }


        // 解析EC值
        private void ParseEC1(byte[] receivedData)
        {
            try
            {
                if (receivedData.Length < 8) return;  // 确保数据长度足够

                // 解析温度（假设大端模式，地址09 7E，2字节）
                byte[] tempBytes = new byte[] { receivedData[3], receivedData[4] };
                bool isBigEndian = true;

                if (isBigEndian)
                {
                    Array.Reverse(tempBytes);
                }

                double temperature1 = BitConverter.ToInt16(tempBytes, 0) / 100.00; // 假设温度有1位小数

                // 解析EC值（地址01 02，2字节）
                byte[] ec1Bytes = new byte[] { receivedData[7], receivedData[8] };

                if (isBigEndian)
                {
                    Array.Reverse(ec1Bytes);
                }

                double ec1Value = BitConverter.ToUInt16(ec1Bytes, 0); // 假设EC值有2位小数

                // 更新UI
                this.BeginInvoke((MethodInvoker)(() =>
                {
                    //textBoxTemperature.Text = $"{temperature} °C";
                    textBox7.Text = $"{ec1Value:F1}"; // 或根据实际单位调整
                }));
            }
            catch (Exception ex)
            {
                //MessageBox.Show("解析数据错误: " + ex.Message);
                ShowAutoCloseMessage($"解析错误: {ex.Message}");
            }
        }

        // 自动关闭的错误弹窗（3秒后消失）
        private async void ShowAutoCloseMessage(string message)
        {
            var dialog = new Form()
            {
                FormBorderStyle = FormBorderStyle.None,
                StartPosition = FormStartPosition.CenterScreen,
                Width = 300,
                Height = 100
            };
            var label = new Label() { Text = message, Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleCenter };
            dialog.Controls.Add(label);
            dialog.Show();

            await Task.Delay(3000); // 等待3秒
            dialog.Close();
        }

        // 解析pH1值
        private void ParsepH1(byte[] receivedData)
        {
            try
            {
                // 数据长度检查（假设最小需要7字节：帧头+温度2字节+pH2字节）
                if (receivedData.Length < 7) return;

                // 解析温度（地址0C 47，2字节，大端模式）
                byte[] tempBytes = new byte[] { receivedData[3], receivedData[4] };
                bool isBigEndian = true;

                if (isBigEndian)
                {
                    Array.Reverse(tempBytes); // 大端转小端
                }

                double temperaturepH = BitConverter.ToUInt16(tempBytes, 0) * 0.01; // 温度×0.01

                // 解析pH值（地址02 CB，2字节，大端模式）
                byte[] ph1Bytes = new byte[] { receivedData[5], receivedData[6] };

                if (isBigEndian)
                {
                    Array.Reverse(ph1Bytes); // 大端转小端
                }

                double ph1Value = BitConverter.ToUInt16(ph1Bytes, 0) * 0.01; // pH×0.01

                // 更新UI（线程安全）
                this.BeginInvoke((MethodInvoker)(() =>
                {
                    //textBoxTemperature.Text = $"{temperature:F2} °C"; // 保留2位小数
                    textBox18.Text = $"{ph1Value:F2}"; // pH无单位或根据需求添加
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show($"解析错误: {ex.Message}", "警告",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }



        //保存数据至本地表格中
        private void SaveDataToExcel()
        {
            try
            {
                ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
                // 设置 Excel 文件路径
                string filePath = @"D:\ProOfDuckweed\Data\SensorDatas.xlsx"; // 更改为你想保存的路径

                // 如果文件不存在，则创建文件
                if (!File.Exists(filePath))
                {
                    FileInfo newFile = new FileInfo(filePath);
                    using (var package = new ExcelPackage(newFile))
                    {
                        var worksheet = package.Workbook.Worksheets.Add("Data");

                        // 写入标题
                        worksheet.Cells[1, 1].Value = "时间";
                        worksheet.Cells[1, 2].Value = "温度(℃)";
                        worksheet.Cells[1, 3].Value = "湿度(%)";
                        worksheet.Cells[1, 4].Value = "光强(Lux)";
                        worksheet.Cells[1, 5].Value = "CO2浓度(ppm)";
                        //worksheet.Cells[1, 6].Value = "水箱水温(℃)";
                        worksheet.Cells[1, 6].Value = "EC(mS/cm)";
                        worksheet.Cells[1, 7].Value = "顶层水温(℃)";
                        worksheet.Cells[1, 8].Value = "总用电量(度)";
                        worksheet.Cells[1, 9].Value = "光量子强度(umol/m2/s)";
                        worksheet.Cells[1, 10].Value = "pH(0-14)";

                        // 保存文件
                        package.Save();
                    }
                }

                while (IsFileInUse(filePath))
                {
                    // **弹出 3 秒后自动关闭的消息**
                    //ShowAutoCloseMessage("Excel 文件已打开，请关闭 Excel！", "文件占用", 3000);

                    // **等待 3 秒后检查是否关闭**
                    Thread.Sleep(3000);

                    // **如果仍然被占用，则弹出新的手动确认弹窗**
                    DialogResult result = MessageBox.Show("请关闭 Excel 后重试！", "文件被占用", MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning);

                    if (result == DialogResult.Cancel)
                    {
                        MessageBox.Show("数据未保存，请稍后重试！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
                }
                if (isPort485Open)
                {
                    // 打开 Excel 文件并写入数据
                    FileInfo file = new FileInfo(filePath);
                    using (var package = new ExcelPackage(file))
                    {
                        var worksheet = package.Workbook.Worksheets[0];  // 获取第一个工作表
                                                                         // 获取最后一行，确保数据不会覆盖
                        int lastRow = worksheet.Dimension?.End.Row ?? 1;
                        int row = lastRow + 1;

                        // 获取当前时间
                        string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                        // 提取温度和湿度数据
                        string[] tempHumData = textBox2.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                        string[] humidity = textBox17.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                        //string temperature = tempHumData.Length > 0 ? tempHumData[0].Replace("温度: ", "").Replace("℃", "").Trim() : "0";
                        //string humidity = tempHumData.Length > 1 ? tempHumData[1].Replace("湿度: ", "").Replace("%", "").Trim() : "0";
                        // 提取EC和&水体温度数据
                        string[] ECTempData = textBox7.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                        string TempInTank = ECTempData.Length > 0 ? ECTempData[0].Replace("水温:", "").Replace("℃", "").Trim() : "0";
                        //string EC = ECTempData.Length > 1 ? ECTempData[1].Replace("EC:", "").Replace("mS/cm", "").Trim() : "0";

                        // 提取光强数据
                        string luminosity = textBox3.Text.Replace("光强: ", "").Replace(" Lux", "").Trim();
             
                        //顶层水温
                        string TopTemp = textBox9.Text.Replace("顶层水温: ", "").Replace(" ℃", "").Trim();
                        //用电量
                        string TotalElectric = textBox10.Text.Replace(" KWh", "").Trim();

                        // 提取 CO2 数据
                        // 获取文本框6中的文本，并替换掉"CO2浓度: "和" ppm"，然后去除首尾空格
                        string CO2 = textBox6.Text.Replace("CO2: ", "").Replace(" ppm", "").Trim();
                        string EC1 = textBox7.Text.Trim();  // 直接获取文本并去除首尾空格
                        string pH1 = textBox18.Text.Trim();  // 直接获取文本并去除首尾空格
                        string PPFD = textBox16.Text.Trim();  // 直接获取文本并去除首尾空格
                        string temperature = textBox16.Text.Trim();  // 直接获取文本并去除首尾空格


                        // 将数据写入 Excel
                        worksheet.Cells[row, 1].Value = currentTime;
                        worksheet.Cells[row, 2].Value = temperature;  // 温度
                        worksheet.Cells[row, 3].Value = humidity;    // 湿度
                        worksheet.Cells[row, 4].Value = luminosity;  // 光强
                        worksheet.Cells[row, 5].Value = CO2;        // CO2浓度
                        worksheet.Cells[row, 6].Value = EC1;        // EC
                        worksheet.Cells[row, 7].Value = TopTemp;  // 顶层水体温度
                        worksheet.Cells[row, 8].Value = TotalElectric;  // 总用电量
                        worksheet.Cells[row, 9].Value = PPFD;  // PPFD
                        worksheet.Cells[row, 10].Value = pH1;  // pH1

                        // 保存文件
                        package.Save();
                    }

                    //MessageBox.Show("数据已保存到 Excel 文件！");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("保存数据时出错: " + ex.Message);
            }
        }

        // **检查 Excel 文件是否被占用**
        private bool IsFileInUse(string filePath)
        {
            if (!File.Exists(filePath)) return false; // 文件不存在，直接返回可用状态

            try
            {
                using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
                {
                    return false; // 能正常打开文件，说明未被占用
                }
            }
            catch (IOException)
            {
                return true; // 发生 IOException，说明文件被占用
            }
            catch (Exception)
            {
                return true; // 其他异常情况，假设文件被占用
            }
        }
        
        //// 控制 LED 亮度的函数 (需要根据你的硬件平台调整 PWM 控制方法)
        //private void SetLEDBrightness(double pwmValue)
        //{
        //    //确保输入的值在0-100%之间
        //    if( pwmValue < 0&& pwmValue > 100)
        //    {
        //        MessageBox.Show("请输入0-100之间的数！");
        //        return;
        //    }
        //    // 你需要实现 LED 控制的代码
        //    // 固定的 Modbus 指令前五个字节
        //    byte[] fixedCommand = new byte[] { 0x05, 0x06, 0x01, 0xF4, 0x00 };
        //    double LEDBrightness = (pwmValue / 100.0) * 255;
        //    // 四舍五入并转换为整数
        //    int roundedLEDBrightness = (int)Math.Round(LEDBrightness);
        //    // 将整数转换为十六进制字符串
        //    string hexLEDBrightness = roundedLEDBrightness.ToString("X");
        //    //MessageBox.Show("hexLEDBrightness: " + hexLEDBrightness);
        //    // 将四舍五入后的亮度值作为字节添加到数组末尾
        //    byte[] commandWithBrightness = new byte[fixedCommand.Length + 1];
        //    fixedCommand.CopyTo(commandWithBrightness, 0);
        //    commandWithBrightness[fixedCommand.Length] = (byte)roundedLEDBrightness;

        //    // 计算 CRC 校验
        //    byte[] crc = ComputeCRC16(commandWithBrightness);

        //    // 将 CRC 校验添加到指令末尾
        //    byte[] fullCommand = new byte[commandWithBrightness.Length + crc.Length];
        //    commandWithBrightness.CopyTo(fullCommand, 0);
        //    crc.CopyTo(fullCommand, commandWithBrightness.Length);
        //    //MessageBox.Show("fullCommand: " + BitConverter.ToString(fullCommand).Replace("-", " "));
        //    //_pwmPort.Write(fullCommand, 0, fullCommand.Length);// 改写发送字符串代码#################
        //    port485_4 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);

        //    port485_4.Open(); // 打开串口
        //    port485_4.Write(fullCommand, 0, fullCommand.Length);
        //    port485_4.Close();
        //}

        // 计算 CRC16 校验
        public static byte[] ComputeCRC16(byte[] data)
        {
            ushort crc = 0xFFFF;
            foreach (byte b in data)
            {
                crc ^= b;
                for (int i = 8; i > 0; i--)
                {
                    if ((crc & 0x0001) != 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);
                    else
                        crc >>= 1;
                }
            }
            return new byte[] { (byte)(crc & 0xFF), (byte)((crc >> 8) & 0xFF) }; // CRC低字节在前
        }

        //控制继电器第一路的开关
        //private void button3_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        //if (!isport485_2)
        //        //{
        //            //创建串口
        //        port485_2 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_2.Open(); // 打开串口
        //        port485_2.Write(Modebus_Data_First_Connect, 0, Modebus_Data_First_Connect.Length); // 发送指令
        //        button3.BackColor = System.Drawing.Color.Green;
        //        button4.BackColor = System.Drawing.Color.Gray;
        //        button3.Text = "1路已连接";
        //        button4.Text = "Close";
        //        port485_2.Close(); // 关闭串口
        //        //isport485_2 = true;                    
        //        //}
        //        //else
        //        //{
        //        //    MessageBox.Show("已打开");
        //        // }
        //    }
        //    catch (Exception )
        //    {
        //        MessageBox.Show("串口打开失败，请检查串口设置！");
        //    }
        //}

        ////###############后面换成根据继电器反馈信号来判断是否已开,一直检测各执行器状态##################
        ////关闭继电器第一路
        //private void button4_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        //if (isport485_2)
        //        //{
        //        port485_3 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_3.Open(); // 打开串口
        //        port485_3.Write(Modebus_Data_First_DisConnect, 0, Modebus_Data_First_DisConnect.Length); // 发送指令
        //        button4.BackColor = System.Drawing.Color.Red;
        //        button3.BackColor = System.Drawing.Color.Gray;
        //        button4.Text = "1路已断开";
        //        button3.Text = "Open";
        //        port485_3.Close(); // 关闭串口
        //        //isport485_2 = false;
        //        //}
        //        //else
        //        //{
        //        //    MessageBox.Show("已关闭");
        //        //}
        //    }
        //    catch (Exception)
        //    {
        //        MessageBox.Show("串口关闭失败，请检查串口设置！");
        //    }
        //}

        ////第二路继电器开----一档（开下面两个风扇）
        //private void button5_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        port485_5 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_5.Open(); // 打开串口
        //        port485_5.Write(Modebus_Data_Third_DisConnect, 0, Modebus_Data_Third_DisConnect.Length); // 发送指0令
        //        Thread.Sleep(1500);
        //        port485_5.Write(Modebus_Data_Second_Connect, 0, Modebus_Data_Second_Connect.Length); // 发送指令
        //        //MessageBox.Show("继电器已连接");
        //        button5.BackColor = System.Drawing.Color.Green;
        //        button6.BackColor = System.Drawing.Color.Gray;
        //        port485_5.Close(); // 关闭串口
        //    }
        //    catch (Exception)
        //    {
        //        MessageBox.Show("串口关闭失败，请检查串口设置！");
        //    }
        //}

        ////第三路继电器开----二档（开下面两个+上面两个，共4个风扇）
        //private void button6_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        port485_5 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_5.Open(); // 打开串口
        //        port485_5.Write(Modebus_Data_Second_Connect, 0, Modebus_Data_Second_Connect.Length); // 发送指令
        //        Thread.Sleep(1500);
        //        port485_5.Write(Modebus_Data_Third_Connect, 0, Modebus_Data_Third_Connect.Length); // 发送指令
        //        button5.BackColor = System.Drawing.Color.Gray;
        //        button6.BackColor = System.Drawing.Color.Green;
        //        port485_5.Close(); // 关闭串口
        //    }
        //    catch (Exception)
        //    {
        //        MessageBox.Show("串口关闭失败，请检查串口设置！");
        //    }
        //}

        ////关闭第2、3路继电器
        //private void button7_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        port485_5 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_5.Open(); // 打开串口
        //        port485_5.Write(Modebus_Data_Second_DisConnect, 0, Modebus_Data_Second_DisConnect.Length); // 发送指令
        //        Thread.Sleep(1000);
        //        port485_5.Write(Modebus_Data_Third_DisConnect, 0, Modebus_Data_Third_DisConnect.Length); // 发送指令
        //        button5.BackColor = System.Drawing.Color.Red;
        //        button6.BackColor = System.Drawing.Color.Red;
        //        port485_5.Close(); // 关闭串口
        //    }
        //    catch (Exception)
        //    {
        //        MessageBox.Show("串口关闭失败，请检查串口设置！");
        //    }
        //}

        //调用matlab函数
        private void button8_Click(object sender, EventArgs e)
        {
            double input_Csharp = double.Parse(textBox7.Text);
            MWNumericArray arr1 = input_Csharp;
            Console.WriteLine(arr1.ToString());
            checkLevel_v1.Class1 MyCheckLevel = new checkLevel_v1.Class1(); //实例化对象
            MWArray result = MyCheckLevel.checkLevel_v1(arr1);
            MWCharArray mwCharArray = (MWCharArray)result;
            string str = mwCharArray.ToString();
            double value = double.Parse(str);


            //获取类型
            //Type type = result.GetType();
            //Console.WriteLine(type.ToString());

            Console.WriteLine(value);
            MessageBox.Show(str);
            //MWNumericArray result = (MWNumericArray)rst; //将matlab函数结果转换为中间过渡格式
            //double output_Csharp = (double)result; //
            //Console.WriteLine(output_Csharp.ToString());
        }


        //Step1:用户输入LED亮度百分值（0-100），相应控制LED亮度
        //step2:用户设定光强值，根据传感器数据判断如何调整LED光强



        //private async void button9_Click(object sender, EventArgs e)
        //{
        //    // 设定允许误差范围
        //    int tolerance = 10;

        //    // 获取目标值并验证
        //    string inputText = textBox8.Text.Trim();
        //    if (!int.TryParse(inputText, out int targetLux) && targetLux > 1 && targetLux < 100)
        //    {
        //        MessageBox.Show("请输入1到100之间的有效整数");
        //        return;
        //    }

        //    try
        //    {
        //        while (true)
        //        {
        //            // 获取当前光强并清理格式
        //            string textbox3Lux = textBox3.Text.Replace("光强: ", "").Replace(" Lux", "").Trim();
        //            if (!int.TryParse(textbox3Lux, out int currentLux))
        //            {
        //                Console.WriteLine("当前光强值无效");
        //                await Task.Delay(2000); // 等待后重试
        //                continue;
        //            }

        //            Console.WriteLine($"Current_Lux_in_Cycle: {currentLux}");
        //            //此处获取一下LED灯的光强值 PreviousLedLux，err=SetLux - 环境Lux - LED Lux
        //            //通过PWM调节模块读取Led通路的值，代表Led此时的开度，进一步可求Led此时光强
        //            int PreviousLedLux = 0; 
        //            int err = Math.Abs(currentLux - targetLux);
        //            //**************0326 下一步需要叠加err,不然无法多次调整，考虑使用PID************
                    
        //            // 检查是否达到目标
        //            if (err <= tolerance)
        //            {
        //                Console.WriteLine("光强已调整到目标值");
        //                MessageBox.Show("光强已调整到目标值");
        //                break;
        //            }

        //            // 更新亮度
        //            if (currentLux < targetLux)
        //            {
        //                int ledBrightness = (int)Math.Ceiling(err / 2.236) - PreviousLedLux;  //这个除数还根据实际情况标定调整
        //                MessageBox.Show($"当前光强：{currentLux},目标光强:{targetLux}, 当前误差: {err}, 调整比例: {ledBrightness}");
        //                SetLEDBrightness(ledBrightness);
        //            }



        //            // 非阻塞等待，让UI线程有机会更新
        //            await Task.Delay(1000*60*5); // 等待光强稳定;等待5分钟再自动检测
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine($"错误: {ex.Message}");
        //        MessageBox.Show($"发生错误: {ex.Message}");
        //    }
        //}

        private void label4_Click(object sender, EventArgs e)
        {

        }

        ////动态调节LED亮度
        //private void button2_Click(object sender, EventArgs e)
        //{
        //    string inputText = textBox4.Text.Trim();
        //    int Vaule = int.Parse(inputText);
        //    // 先检查是否为空
        //    if (string.IsNullOrEmpty(inputText))
        //    {
        //        MessageBox.Show("输入不能为空");
        //        return;
        //    }
        //    // 检查是否包含小数点
        //    if (inputText.Contains("."))
        //    {
        //        MessageBox.Show("请输入整数，不能包含小数");
        //        return;
        //    }
        //    // 尝试转换为整数
        //    if (int.TryParse(inputText, out int value))
        //    {
        //        // 检查范围
        //        if (value < 0 || value > 100)
        //        {
        //            MessageBox.Show("请输入0到100之间的整数"); // 范围不符的提示
        //        }
        //    }
        //    else
        //    {
        //        MessageBox.Show("请输入有效的整数"); // 无效输入的提示
        //    }
        //    //int Value = 0;
        //    Console.WriteLine("value",value);
        //    SetLEDBrightness(value);
        //}

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        //定时开启水泵
        //private void button12_Click(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        //if (!isport485_2)
        //        //{
        //        //创建串口
        //        port485_2 = new SerialPort($"{textBox5.Text}", 9600, Parity.None, 8, StopBits.One);
        //        port485_2.Open(); // 打开串口
        //        port485_2.Write(Modebus_Data_First_Connect, 0, Modebus_Data_First_Connect.Length); // 发送指令
        //        button3.BackColor = System.Drawing.Color.Green;
        //        button4.BackColor = System.Drawing.Color.Gray;
        //        button3.Text = "1路已连接";
        //        button4.Text = "Close";
        //        port485_2.Close(); // 关闭串口
        //        //isport485_2 = true;                    
        //        //}
        //        //else
        //        //{
        //        //    MessageBox.Show("已打开");
        //        // }
        //    }
        //    catch (Exception)
        //    {
        //        MessageBox.Show("串口打开失败，请检查串口设置！");
        //    }
        //}

        //采收水泵的【开】控制
        private void button8_Click_1(object sender, EventArgs e)
        {
            try
            {
                //if (!isport485_2)
                //{
                //创建串口
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_First_Connect, 0, DAM_First_Connect.Length); // 发送指令
                button8.BackColor = System.Drawing.Color.Green;
                button10.BackColor = System.Drawing.Color.Gray;
                //button3.Text = "1路已连接";
                //button4.Text = "Close";
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        private void button10_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_First_DisConnect, 0, DAM_First_DisConnect.Length); // 发送指令
                button10.BackColor = System.Drawing.Color.Green;
                button8.BackColor = System.Drawing.Color.Gray;
                //button3.Text = "1路已连接";
                //button4.Text = "Close";
                port485_2.Close(); // 关闭串口
                //isport485_2 = true;                    
                //}
                //else
                //{
                //    MessageBox.Show("已打开");
                // }
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        void TurnOnCHWP()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Second_Connect, 0, DAM_Second_Connect.Length); // 发送指令
                //button11.BackColor = System.Drawing.Color.Green;
                //button13.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }
        void TurnOffCHWP()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Second_DisConnect, 0, DAM_Second_DisConnect.Length); // 发送指令
                //button13.BackColor = System.Drawing.Color.Green;
                //button11.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }


        //制冷水泵【开】
        private void button11_Click(object sender, EventArgs e)
        {
            try
            {
                //if (!isport485_2)
                //{
                //创建串口
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Second_Connect, 0, DAM_Second_Connect.Length); // 发送指令
                button11.BackColor = System.Drawing.Color.Green;
                button13.BackColor = System.Drawing.Color.Gray;
                //button3.Text = "1路已连接";
                //button4.Text = "Close";
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //制冷水泵【关】
        private void button13_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Second_DisConnect, 0, DAM_Second_DisConnect.Length); // 发送指令
                button13.BackColor = System.Drawing.Color.Green;
                button11.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //植物灯的【开】控制
        private void button12_Click_1(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_Connect, 0, DAM_Third_Connect.Length); // 发送指令
                button12.BackColor = System.Drawing.Color.Green;
                button14.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //植物灯的【关】控制
        private void button14_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_DisConnect, 0, DAM_Third_DisConnect.Length); // 发送指令
                button14.BackColor = System.Drawing.Color.Green;
                button12.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        public async Task DoDelayedOperationAsync()
        {
            Console.WriteLine("start");
            button15.BackColor = System.Drawing.Color.Green;
            if (double.TryParse(textBox11.Text, out double SetTime))
            {
                await Task.Delay(TimeSpan.FromMilliseconds(SetTime*1000*60));
                Console.WriteLine("stop");
                button15.BackColor = System.Drawing.Color.Gray;
            }
            else
            {
                MessageBox.Show("请输入有效的数字");
            }
        }

        //定时控制关闭植物灯。textbox11输入x分钟，则立马开灯，然后x分钟后关灯。
        private async void button15_Click(object sender, EventArgs e)
        {

            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_Connect, 0, DAM_Third_Connect.Length); // 发送指令
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }

            try
            {
                await DoDelayedOperationAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发生错误：{ex.Message}");
            }
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_DisConnect, 0, DAM_Third_DisConnect.Length); // 发送指令
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //out4【开】
        private void button16_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fourth_Connect, 0, DAM_Fourth_Connect.Length); // 发送指令
                button16.BackColor = System.Drawing.Color.Green;
                button17.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //out4【关】
        private void button17_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fourth_DisConnect, 0, DAM_Fourth_DisConnect.Length); // 发送指令
                button17.BackColor = System.Drawing.Color.Green;
                button16.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }


        //OUT5[开]
        private void button3_Click_1(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fifth_Connect, 0, DAM_Fifth_Connect.Length); // 发送指令
                button3.BackColor = System.Drawing.Color.Green;
                button2.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //OUT5【关】
        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fifth_DisConnect, 0, DAM_Fifth_DisConnect.Length); // 发送指令
                button2.BackColor = System.Drawing.Color.Green;
                button3.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //OUT6[开]
        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Sixth_Connect, 0, DAM_Sixth_Connect.Length); // 发送指令
                button5.BackColor = System.Drawing.Color.Green;
                button4.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //OUT6【关】
        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Sixth_DisConnect, 0, DAM_Sixth_DisConnect.Length); // 发送指令
                button4.BackColor = System.Drawing.Color.Green;
                button5.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }


        // 温度检测逻辑（在后台线程运行）
        // 后台温度监控逻辑
        private void MonitorTemperature(double highThreshold, double lowThreshold, CancellationToken token)
        {
            try
            {
                while (!token.IsCancellationRequested)
                {
                    double currentTemp;
                    // 从文本提取当前温度（示例："顶层水温28℃"）
                    var match = Regex.Match(textBox9.Text, @"\d+(\.\d+)?");
                    if (!match.Success)
                    {
                        MessageBox.Show("未检测到温度数值！");
                        return;
                    }
                    // 3. 转换温度值
                    if (!double.TryParse(match.Value, out currentTemp))
                    {
                        MessageBox.Show("温度格式无效！");
                        return;
                    }
                        
                    // 控制逻辑
                    if (currentTemp > highThreshold)
                    {
                        TurnOnCHWP();
                        button6.BackColor = System.Drawing.Color.Green;
                    }
                    else if (currentTemp <= lowThreshold)
                    {
                        TurnOffCHWP();
                        button6.BackColor = System.Drawing.Color.Gray;
                    }

                    // 每分钟检测一次（可调整间隔）
                    Thread.Sleep(1000 * 60);
                }
            }
            catch (OperationCanceledException)
            {
                // 任务被取消时退出
            }
        }

        //水温自起停，温度高于设定值后开启制冷水泵，接着，降低水温至设定值后关闭水泵
        private async void button6_Click(object sender, EventArgs e)
        {
            // 验证输入
            if (!double.TryParse(textBox4.Text, out double highThreshold) ||
                !double.TryParse(textBox5.Text, out double lowThreshold))
            {
                MessageBox.Show("请输入有效的温度阈值！");
                return;
            }
            button6.BackColor = System.Drawing.Color.Gray;
            // 取消之前的任务（避免重复启动）
            _cts?.Cancel();
            _cts = new CancellationTokenSource();

            // 启动后台任务（不阻塞UI）
            await Task.Run(() => MonitorTemperature(highThreshold, lowThreshold, _cts.Token));

        }

        //每日定时开启植物灯功能
        private void button7_Click(object sender, EventArgs e)
        {
            // 解析用户选择的时间
            userOpenTime = ParseComboBoxTime(openTimeComboBox.SelectedItem?.ToString());
            //Console.WriteLine(userOpenTime);
            userCloseTime = ParseComboBoxTime(closeTimeComboBox.SelectedItem?.ToString());
            // 验证时间有效性
            if (!userOpenTime.HasValue || !userCloseTime.HasValue)
            {
                MessageBox.Show("请确保选择有效的开启和关闭时间", "错误");
                return;
            }
            // 启动定时器（若未运行）
            if (!isLEDTimerRunning)
            {
                LEDtimer.Start();
                isLEDTimerRunning = true;
                button7.BackColor = System.Drawing.Color.Blue;
            }

        }
        private void LEDTimer_Tick(object sender, EventArgs e)
        {
            CheckTimeAndTriggerFunction();
        }

        private TimeSpan? ParseComboBoxTime(string timeString)
        {
            if (string.IsNullOrEmpty(timeString))
            {
                System.Diagnostics.Debug.WriteLine("ParseComboBoxTime: 输入字符串为空");
                return null;
            }
            if (TimeSpan.TryParseExact(timeString, @"hh\:mm", null, out TimeSpan time))
            {
                return new TimeSpan(time.Hours, time.Minutes, time.Seconds);
            }
            System.Diagnostics.Debug.WriteLine($"ParseComboBoxTime: 解析失败，输入: {timeString}");
            return null;
        }

        private void CheckTimeAndTriggerFunction()
        {
            // 获取当前时间
            DateTime now = DateTime.Now;
            TimeSpan currentTime = new TimeSpan(now.Hour, now.Minute, 0);

            if (!userOpenTime.HasValue || !userCloseTime.HasValue)
            {
                return;
            }

            bool shouldBeOn;
            if (userOpenTime.Value <= userCloseTime.Value)
            {
                // 非跨天情况：开启时间 <= 关闭时间
                shouldBeOn = currentTime >= userOpenTime.Value && currentTime < userCloseTime.Value;
            }
            else
            {
                // 跨天情况：开启时间 > 关闭时间
                shouldBeOn = currentTime >= userOpenTime.Value || currentTime < userCloseTime.Value;
            }

            // 根据时间范围控制继电器
            if (shouldBeOn && !isLEDRelayOn)
            {
                //ControlRelay(true);
                //MessageBox.Show("Start");
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_Connect, 0, DAM_Third_Connect.Length); // 发送指令
                port485_2.Close(); // 关闭串口
                isLEDRelayOn = true;
                button7.BackColor = System.Drawing.Color.Green;
            }
            else if (!shouldBeOn && isLEDRelayOn)
            {
                //ControlRelay(false);

                isLEDRelayOn = false;
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Third_DisConnect, 0, DAM_Third_DisConnect.Length); // 发送指令
                //button14.BackColor = System.Drawing.Color.Green;
                button12.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
                //MessageBox.Show("End");
            }

            // 调试：输出时间信息
            //System.Diagnostics.Debug.WriteLine(
                //$"当前时间: {currentTime}, 开启时间: {userOpenTime?.ToString() ?? "未设置"}, " +
                //$"关闭时间: {userCloseTime?.ToString() ?? "未设置"}, 继电器应为: {(shouldBeOn ? "开启" : "关闭")}"
            //);
        }

        //控制加注营养液的水泵
        private async void button9_Click(object sender, EventArgs e)
        {
            // 验证输入
            if (!double.TryParse(textBox8.Text, out double LowECThreshold) ||
                !double.TryParse(textBox12.Text, out double HighECThreshold))
            {
                MessageBox.Show("请输入有效的温度阈值！");
                return;
            }
            button9.BackColor = System.Drawing.Color.Gray;
            // 取消之前的任务（避免重复启动）
            _cts?.Cancel();
            _cts = new CancellationTokenSource();

            // 启动后台任务（不阻塞UI）
            await Task.Run(() => MonitorEC(LowECThreshold, HighECThreshold, _cts.Token));

        }

        // 后台温度监控逻辑
        private void MonitorEC(double LowECThreshold, double HighECThreshold, CancellationToken token)
        {
            try
            {
                while (!token.IsCancellationRequested)
                {
                    double currentTemp;
                    // 从文本提取当前EC
                    var match = Regex.Match(textBox7.Text, @"EC:\s*(\d+)\b");
                    string ECVaule = match.Groups[1].Value;
                    if (int.TryParse(ECVaule, out int ECnumCur))
                    {
                        //Console.WriteLine($"转换成功");  // 输出: 123
                    }
                    else
                    {
                        Console.WriteLine("转换失败，输入不是有效整数！");
                    }
                    if (!match.Success)
                    {
                        MessageBox.Show("未检测到EC数值！");
                        return;
                    }
                    // 控制逻辑
                    if (ECnumCur <= LowECThreshold)
                    {
                        TurnOnRelay5();
                        button9.BackColor = System.Drawing.Color.Green;
                    }
                    else if (ECnumCur >= HighECThreshold)
                    {
                        TurnOffRelay5();
                        button9.BackColor = System.Drawing.Color.Red;
                    }

                    // 每5秒钟检测一次（可调整间隔）
                    Thread.Sleep(1000 * 5);
                }
            }
            catch (OperationCanceledException)
            {
                // 任务被取消时退出
            }
        }
        //打开第五路继电器
        void TurnOnRelay5()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fifth_Connect, 0, DAM_Fifth_Connect.Length); // 发送指令
                //button11.BackColor = System.Drawing.Color.Green;
                //button13.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }
        //关闭第五路继电器
        void TurnOffRelay5()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Fifth_DisConnect, 0, DAM_Fifth_DisConnect.Length); // 发送指令
                //button11.BackColor = System.Drawing.Color.Green;
                //button13.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }

        //间隔定时-实验需要
        private async void button18_Click(object sender, EventArgs e)
        {

            if (!int.TryParse(textBox15.Text, out durationSeconds) || durationSeconds <= 0)
            {
                MessageBox.Show("请输入有效的正整数值！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!int.TryParse(textBox14.Text, out durationMinutes) || durationMinutes <= 0)
            {
                MessageBox.Show("请输入有效的正整数值！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            button18.BackColor = System.Drawing.Color.Blue;
            var controlTask = ControlCO2Cycle();

            await controlTask; // 如果程序退出，任务会自动终止
        }

        //CO2控制任务
        private async Task ControlCO2Cycle()
        {
            try
            {
                while (true)
                {
                    //后续释放以下代码
                    //// 每分钟检查一次时间范围
                    //DateTime now = DateTime.Now;
                    //int currentHour = now.Hour;
                    //int currentMinute = now.Minute;
                    //bool isWithinTimeRange = false;

                    //// 定义时间范围 (20:30 至 06:30 JST)
                    //int startHour = 20;
                    //int startMinute = 30;
                    //int endHour = 6;
                    //int endMinute = 30;

                    //// 判断是否在 20:30 至 06:30 之间
                    //if (currentHour >= startHour || currentHour < endHour)
                    //{
                    //    if (currentHour == startHour && currentMinute < startMinute) continue; // 未到 20:30
                    //    if (currentHour == endHour && currentMinute >= endMinute) continue;    // 已过 06:30
                    //    isWithinTimeRange = true;
                    //}

                    //if (!isWithinTimeRange)
                    //{
                    //    Console.WriteLine($"[{DateTime.Now}] CO2控制已停止，当前时间 {currentHour}:{currentMinute} 不在 20:30-06:30 范围内");
                    //    button18.BackColor = System.Drawing.Color.Gray;
                    //    break; // 跳出循环
                    //}

                    // 1. 开启CO2
                    isCO2On = true;
                    //Console.WriteLine($"[{DateTime.Now}] CO2开启，持续 {durationSeconds} 秒");
                    TurnOnCO2(); // 替换为实际硬件控制
                                 //Console.WriteLine(1);
                    button18.BackColor = System.Drawing.Color.Green;
                    // 2. 等待持续时间结束
                    await Task.Delay(TimeSpan.FromSeconds(durationSeconds));
                    //Console.WriteLine(2);
                    // 3. 关闭CO2
                    TurnOffCO2(); // 替换为实际硬件控制
                    isCO2On = false;
                    //Console.WriteLine($"[{DateTime.Now}] CO2已关闭");

                    // 4. 等待到下一个3小时周期
                    await Task.Delay(TimeSpan.FromMinutes(durationMinutes) - TimeSpan.FromSeconds(durationSeconds));
                }
            }
            catch (TaskCanceledException)
            {
                Console.WriteLine("CO2控制循环已停止");
            }
        }

        //开启第六路继电器-即打开CO2发生器
        void TurnOnCO2()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Sixth_Connect, 0, DAM_Sixth_Connect.Length); // 发送指令
                //button11.BackColor = System.Drawing.Color.Green;
                //button13.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }
        //关闭第六路继电器-即关闭CO2发生器
        void TurnOffCO2()
        {
            try
            {
                port485_2 = new SerialPort($"{textBox13.Text}", 9600, Parity.None, 8, StopBits.One);
                port485_2.Open(); // 打开串口
                port485_2.Write(DAM_Sixth_DisConnect, 0, DAM_Sixth_DisConnect.Length); // 发送指令
                //button11.BackColor = System.Drawing.Color.Green;
                //button13.BackColor = System.Drawing.Color.Gray;
                port485_2.Close(); // 关闭串口
            }
            catch (Exception)
            {
                MessageBox.Show("串口打开失败，请检查串口设置！");
            }
        }
    }
}
